#!/bin/bash

######################################################################
#
#  Copyright (c) 2015 arakasi72 (https://github.com/arakasi72)
#
#  --> Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
#
######################################################################

###############################
### SET VARIABLES ###
###############################

PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/bin:/sbin
passfile='/etc/nginx/.htpasswd'

scgi_port_start=5000
rpc_start=2
rtport_start=51001
sshport=$(grep 'Port ' /etc/ssh/sshd_config | sed 's/[^0-9]*//g')
ftpport=$(grep 'listen_port=' /etc/vsftpd.conf | sed 's/[^0-9]*//g')
cronline1="@reboot sleep 10; /usr/local/bin/rtcheck irssi rtorrent"
cronline2="*/10 * * * * /usr/local/bin/rtcheck irssi rtorrent"
serverip=$(ip route get 8.8.8.8 | awk 'NR==1 {print $NF}')
check_ssh=1

#get user list
cd /var/www/rutorrent/conf/users
user_list=*

###############################
### FUNCTIONS ###
###############################

genpasswd() {
local genln=$1
[ -z "$genln" ] && genln=8
tr -dc A-Za-z0-9 < /dev/urandom | head -c ${genln} | xargs
}

random()
{
    local min=$1
    local max=$2
    local RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
    RAND=$((RAND%((($max-$min)+1))+$min))
    echo $RAND
}

find_port() {
local port_count=$1
local port_type=$2
local no_match=1

while [[ $no_match -ne 0 ]]
  do
    if [[ $port_type = "adl" ]]; then
      port_count=$(random 34000 39000)
    else
     port_count=$(( $port_count + 1 ))
    fi

    for i in $user_list
      do
        current_user=$i
        current_port=$(grep $port_type /var/www/rutorrent/conf/users/$current_user/config.php | sed 's/[^0-9]*//g')
        if [[ $current_port = $port_count ]]; then
          no_match=1
          break
        else
          no_match=0
        fi
      done
  done

echo $port_count
}

find_range() {
local low_count=$1
local high_count=$(( $low_count +249 ))
local no_match=1
local higher=0
while [[ $no_match -eq 1 ]]
  do
    low_count=$(( $low_count + 250 ))
    high_count=$(( $high_count + 250 ))
    for i in $user_list
      do
       base_user=$i
       base_home=$(eval echo "~$base_user")
       base_low=$(grep "port_range" $base_home/.rtorrent.rc | sed 's/[^0-9-]*//g' | cut -d- -f1)
       base_high=$(grep "port_range" $base_home/.rtorrent.rc | sed 's/[^0-9-]*//g' | cut -d- -f2)
       if [[ $low_count -gt $base_high ]]; then
         no_match=0
         higher=0
       elif [[ $high_count -lt $base_low ]]; then
         no_match=0
         higher=1
       else
         no_match=1
         break
       fi

       for n in $user_list
         do
           compare_user=$n
           compare_home=$(eval echo "~$compare_user")
           if [[ $no_match -eq 1 ]]; then
             break
           fi

           if [[ $base_user != $compare_user ]]; then
             compare_low=$(grep "port_range" $compare_home/.rtorrent.rc | sed 's/[^0-9-]*//g' | cut -d- -f1)
             compare_high=$(grep "port_range" $compare_home/.rtorrent.rc | sed 's/[^0-9-]*//g' | cut -d- -f2)

             if [[ $higher -eq 0 ]]; then
               if [[ $base_low -gt $compare_high ]]; then
                 no_match=0
               elif [[ $high_count -lt $compare_low ]]; then
                 no_match=0
               elif [[ $compare_low -gt $base_high && $compare_high -lt $low_count ]]; then
                 no_match=0
               else
                 no_match=1
                 break
               fi
           fi

           if [[ $higher -eq 1 ]]; then
             if [[ $base_high -lt $compare_low ]]; then
               no_match=0
             elif [[ $low_count -gt $compare_high ]]; then
               no_match=0
             elif [[ $compare_high -lt $base_low && $compare_low -gt $high_count ]]; then
               no_match=0
             else
               no_match=1
               break
             fi
           fi
         fi
         done
      done
  done
echo "$low_count-$high_count"
}

###############################
### INITIAL SYSTEM CHECKS ###
###############################

# set and prepare user
if [ "$(id -u)" != "0" ]; then
  echo "Must be run from root or using sudo" && exit 1
fi

# get options
OPTS=$(getopt -n "$0" -o snu:p:w: --long "ssh-access,no-ssh,user:,password:,webpass:" -- "$@")

eval set -- "$OPTS"

while true; do
  case "$1" in
    -s | --ssh-access ) check_ssh=0; sshaccess=0; shift;;
    -n | --no-ssh ) check_ssh=0; sshaccess=1; shift;;
    -u | --user ) user="$2"; shift; shift;;
    -p | --password ) unixpass="$2"; shift; shift;;
    -w | --webpass ) webpass="$2"; shift; shift;;
    -- ) shift; break ;;
     * ) break ;;
  esac
done

if [ "$user" = "root" ]; then
      echo "Cannot create root"
      exit
fi

###############################
### ADD USER ###
###############################

if [ -z "$user" ]; then
  echo "Enter the name of the user to add"
  echo "It can be an existing user or a new user"
  echo

  confirm_name=1
  while [ $confirm_name = 1 ]
    do
      read -p "Enter user name: " answer
      addname=$answer
      check_name=1
      if [ "$addname" = "root" ]; then
        echo "Cannot create root"
        exit
      fi

      while [ $check_name = 1 ]
        do
          read -p "Is $addname correct? " answer
          case $answer in [Yy]* ) confirm_name=0 && check_name=0  ;;
                          [Nn]* ) confirm_name=1 && check_name=0  ;;
                              * ) echo "Enter y or n";;
          esac
        done
    done

  user=$addname
fi

if id -u $user >/dev/null 2>&1; then
  echo "$user already exists"
else
  if [ -z "$unixpass" ]; then
    adduser --gecos "" $user
  else
    adduser --gecos "" $user --disabled-password
    echo "$user:$unixpass" | sudo chpasswd
  fi
fi

home=$(eval echo "~$user")

if [ -d "/var/www/rutorrent/conf/users/$user" ]; then
  echo "Will reset $user config, filters and torrents will not be deleted"
fi

if groups $user | grep -q -E ' sshuser(\s|$)' || groups $user | grep -q -E ' sudo(\s|$)'; then
  echo "ssh already granted"
  check_ssh=0
fi

 while [ $check_ssh = 1 ]
   do
     read -p "Grant $user ssh access? " answer
     case $answer in [Yy]* ) sshaccess=0  check_ssh=0  ;;
                     [Nn]* ) sshaccess=1  check_ssh=0  ;;
                         * ) echo "Enter y or n";;
      esac
   done

if [ "$sshaccess" = "0" ]; then
      adduser $user sshuser
fi

if [ "$user" = "$SUDO_USER" ]; then
  echo "Will reset $user config, autodl filters and torrents will not be deleted"
  cp -f /etc/rtinst/conf/ru.config /var/www/rutorrent/conf/config.php 
fi

###############################
### CONFIGURE APPLICATIONS ###
###############################

#remove existing directory if there
if [ -d "/var/www/rutorrent/conf/users/$user" ]; then
  rm -r /var/www/rutorrent/conf/users/$user
fi

#assign ports
newscgi=$(find_port $scgi_port_start scgi)
newrpc=$(find_port $rpc_start RPC)
adlport=$(find_port $(random 34000 39000) adl)
adlpass=$(genpasswd $(random 12 16))
newrange=$(find_range $rtport_start)

#add directories and config files
mkdir /var/www/rutorrent/conf/users/$user
mkdir /var/www/rutorrent/conf/users/$user/plugins

if ! [ -d "$home/rtorrent" ]; then
mkdir $home/rtorrent
fi

if ! [ -d "$home/rtorrent/.session" ]; then
mkdir $home/rtorrent/.session
fi

if ! [ -d "$home/rtorrent/download" ]; then
mkdir $home/rtorrent/download
fi

if ! [ -d "$home/rtorrent/watch" ]; then
mkdir $home/rtorrent/watch
fi

if [ -z "$webpass" ] && [ -z $(grep -s $user $passfile) ]; then
  webpass=$(genpasswd)
fi

if [ ! -z "$webpass" ]; then
  htpasswd -b $passfile $user $webpass
fi

cp -f /etc/rtinst/conf/rtorrent.rc $home/.rtorrent.rc

sed -i "s|<user home>|${home}|g" $home/.rtorrent.rc
sed -i "s/<user name>/$user/g" $home/.rtorrent.rc
sed -i "s/port_range = 51001-51250/port_range = $newrange/g" $home/.rtorrent.rc
sed -i "s/network\.port_range\.set = 51001-51250/network\.port_range\.set = $newrange/g" $home/.rtorrent.rc
sed -i "s/network\.scgi\.open_port = 127\.0\.0\.1:5000/network\.scgi\.open_port = 127\.0\.0\.1:$newscgi/g" $home/.rtorrent.rc

echo "<?php" > /var/www/rutorrent/conf/users/$user/config.php
echo >> /var/www/rutorrent/conf/users/$user/config.php
echo "\$homeDirectory = \"$home\";" >> /var/www/rutorrent/conf/users/$user/config.php
echo "\$topDirectory = \"$home\";" >> /var/www/rutorrent/conf/users/$user/config.php
echo "\$scgi_port = $newscgi;" >> /var/www/rutorrent/conf/users/$user/config.php
echo "\$XMLRPCMountPoint = \"/RPC$newrpc\";" >> /var/www/rutorrent/conf/users/$user/config.php
echo >> /var/www/rutorrent/conf/users/$user/config.php
echo "?>" >> /var/www/rutorrent/conf/users/$user/config.php

###############################
### AUTODL-IRSSI ###
###############################
mkdir /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi
mkdir -p $home/.irssi/scripts/autorun
cd $home/.irssi/scripts
curl -sL http://git.io/vlcND | grep -Po '(?<="browser_download_url": ")(.*-v[\d.]+.zip)' | xargs wget --quiet -O autodl-irssi.zip
unzip -o autodl-irssi.zip >> /dev/null 2>&1
rm autodl-irssi.zip
cp autodl-irssi.pl autorun/
mkdir -p $home/.autodl

echo "<?php" > /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php
echo >> /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php
echo "\$autodlPort = $adlport;" >> /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php
echo "\$autodlPassword = \"$adlpass\";" >> /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php
echo >> /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php
echo "?>" >> /var/www/rutorrent/conf/users/$user/plugins/autodl-irssi/conf.php

cd $home/.autodl

if [ -f "autodl.cfg" ]; then
  if (grep -sq gui-server-port autodl.cfg) && (grep -sq gui-server-password autodl.cfg); then
    sed -i "/gui-server-port/ c\gui-server-port = $adlport" autodl.cfg
    sed -i "/gui-server-password/ c\gui-server-password = $adlpass" autodl.cfg
  else
    sed -i '/gui-server-port/ d' autodl.cfg
    sed -i '/gui-server-password/ d' autodl.cfg
    echo >> autodl.cfg
    sed -i "1s/^/[options]\ngui-server-port = $adlport\ngui-server-password = $adlpass\n/" autodl.cfg
  fi
else
  echo "[options]" > autodl.cfg
  echo "gui-server-port = $adlport" >> autodl.cfg
  echo "gui-server-password = $adlpass" >> autodl.cfg
fi

chown -R $user:$user $home
chown -R www-data:www-data /var/www/rutorrent

if [ -z "$(crontab -u $user -l | grep "$cronline1")" ]; then
  (crontab -u $user -l; echo "$cronline1" ) | crontab -u $user -
fi

if [ -z  "$(crontab -u $user -l | grep "\*/10 \* \* \* \* /usr/local/bin/rtcheck irssi rtorrent")" ]; then
  (crontab -u $user -l; echo "$cronline2" ) | crontab -u $user -
fi

su $user -c '/usr/local/bin/rt restart'
su $user -c '/usr/local/bin/rt -i restart'

dload_line=$(grep "include /etc/nginx/conf.d/rtdload;" /etc/nginx/sites-available/default)
dload_hash=$(echo $dload_line | sed 's/[^#]*//g')
if [ ! -z "$dload_line" -a -z "$dload_hash" ]; then
dload_flag=0
else
dload_flag=1
fi

echo "$user setup complete"
echo "SCGI Port: $newscgi"
echo "RPC Mount: $newrpc"
echo "rtorrent port range $newrange"
echo "autodl port: $adlport"
echo "autodl pass: $adlpass"
echo "crontab entries made, rtorrent and irssi will start on boot"
echo

###############################
### WRITE RTINST.INFO ###
###############################

echo > $home/rtinst.info
if groups $user | grep -q -E ' sshuser(\s|$)' || groups $user | grep -q -E ' sudo(\s|$)'; then
echo "$user has SSH access on port $sshport" | tee -a $home/rtinst.info
echo
fi
echo "ftp client should be set to explicit ftp over tls using port $ftpport" | tee -a $home/rtinst.info
echo
if [ $dload_flag = 0 ]; then
echo "https downloads can be accessed at https://$serverip/download/$user" | tee -a $home/rtinst.info
echo
fi
echo "rutorrent can be accessed at https://$serverip/rutorrent" | tee -a $home/rtinst.info
if [ -z $webpass ]; then
  echo "rutorrent password has not been changed" | tee -a $home/rtinst.info
else
  echo "rutorrent password set to $webpass" | tee -a $home/rtinst.info
fi
echo "to change rutorrent password enter: rtpass" | tee -a $home/rtinst.info
echo
echo "The above info is stored at $home/rtinst.info"
chown $user:$user $home/rtinst.info
